#include "Util.h"
vector<wstring> Util::lineQueue;

Util::Util(const LPDIRECT3DDEVICE9 device) : DeviceHolder(device)
{
	setupFonts();
}

Util::~Util(void)
{
	g_font->Release();
	lineQueue.clear();
}

void Util::setupFonts()
{
	HRESULT hr = D3DXCreateFont(
		device,
		fontHeight,//Font height
		fontWidth,//Font width
		FW_NORMAL,//Font Weight
		0,//MipLevels
		false,//Italic
		ANSI_CHARSET,//CharSet
		OUT_DEFAULT_PRECIS,//OutputPrecision
		DEFAULT_QUALITY,//Quality
		DEFAULT_PITCH | FF_DONTCARE,//PitchAndFamily
		L"Arial",//pFacename,
		&g_font);//ppFont
	SHOW_ERROR_MSG(hr, L"Error creating font.");
}

void Util::renderText() const
{
	SHOW_ERROR_MSG(device->BeginScene(), L"BeginScene failed.");

	UINT index = 0;
	for (vector<wstring>::const_iterator itr = lineQueue.begin(); itr != lineQueue.end(); ++itr)
	{
		wstring str = static_cast<wstring>(*itr);
		for (wstring::iterator itr = str.begin(); itr != str.end(); ++itr)
		{
			char cr = static_cast<char>(*itr);
			if (cr =='^')
			{
				str.replace(itr,itr+1,L" ");
			}
		}

		RECT font_rect;
		SetRect(
			&font_rect,
			0,
			fontHeight * index,
			SCREEN_WIDTH, 
			fontHeight + 2);

		g_font->DrawText(
			NULL,//pSprite
			str.c_str(),//pString
			str.size() * 2,//Count
			&font_rect,//pRect
			DT_LEFT|DT_NOCLIP,//Format,
			0xFF000000); //Color
		
		font_rect.top += 1;
		font_rect.left += 1;

		g_font->DrawText(
			NULL,//pSprite
			str.c_str(),//pString
			str.size() * 2,//Count
			&font_rect,//pRect
			DT_LEFT|DT_NOCLIP,//Format,
			0xFFFFFFFF); //Color
		index++;
	}
	SHOW_ERROR_MSG(device->EndScene(), L"End scene field");
	lineQueue.clear();
}

void Util::drawSurface(IDirect3DSurface9 *surface, const LONG xOff, const LONG yOff) const
{
	RECT destRect;
	destRect.top = yOff;
	destRect.left = xOff;
	destRect.right = (SCREEN_WIDTH / 2) + xOff;
	destRect.bottom = (SCREEN_HEIGHT / 2) + yOff;

	IDirect3DSurface9* bbuf = NULL;
	HRESULT hr = device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &bbuf);
	SHOW_ERROR_MSG(hr, L"Error getting back bufffer.");

	device->StretchRect(surface, NULL, bbuf, &destRect, D3DTEXF_NONE);
	SHOW_ERROR_MSG(hr, L"Stretch rect error.");

	bbuf->Release();
}

FLOAT Util::time()
{
	static __int64 start = 0;
	static __int64 frequency = 0;

	if (start == 0)
	{
		QueryPerformanceCounter((LARGE_INTEGER*)&start);
		QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
		return 0.0f;
	}
	__int64 counter = 0;
	QueryPerformanceCounter((LARGE_INTEGER*)&counter);
	return (float) ((counter - start) / double(frequency));
}


LPD3DXMESH Util::generateQuad()
{
	HRESULT hr = 0;
	LPD3DXMESH quad = NULL;

	hr = D3DXCreateMesh(
		2,
		4,
		D3DUSAGE_WRITEONLY,
		vertexInfo::VERTEX_FORMAT,
		device,
		&quad);
	SHOW_ERROR_MSG(hr, L"Error creating quad mesh.");

	// Vertex Buffer
	{
		vertexInfo::D3DVERTEX *vtx = NULL;
		hr = quad->LockVertexBuffer(0, (void**)&vtx);
		SHOW_ERROR_MSG(hr, L"Error locking vertex buffer.");

		vtx[0] = vertexInfo::D3DVERTEX(
			D3DXVECTOR3(-1,	1,	0.0f),
			D3DXVECTOR3(0.0f,	0.0f,	1.0f),
			D3DXVECTOR2(0,	0),
			D3DXVECTOR3(0.0f,	0.0f,	0.0f));
		vtx[1] = vertexInfo::D3DVERTEX(
			D3DXVECTOR3(1,	1,	0.0f),
			D3DXVECTOR3(0.0f,	0.0f,	1.0f),
			D3DXVECTOR2(1,	0),
			D3DXVECTOR3(0.0f,	0.0f,	0.0f));
		vtx[2] = vertexInfo::D3DVERTEX(
			D3DXVECTOR3(1,	-1,	0.0f),
			D3DXVECTOR3(0.0f,	0.0f,	1.0f),
			D3DXVECTOR2(1,	1),
			D3DXVECTOR3(0.0f,	0.0f,	0.0f));
		vtx[3] = vertexInfo::D3DVERTEX(
			D3DXVECTOR3(-1,	-1,	0.0f),
			D3DXVECTOR3(0.0f,	0.0f,	1.0f),
			D3DXVECTOR2(0,	1),
			D3DXVECTOR3(0.0f,	0.0f,	0.0f));

		hr = quad->UnlockVertexBuffer();
		SHOW_ERROR_MSG(hr, L"Error unlocking vertex buffer.");
	}

	// Index Buffer
	{
		WORD *idx = 0;
		hr = quad->LockIndexBuffer(0, (void**)&idx);
		SHOW_ERROR_MSG(hr, L"Error locking index buffer.");

		idx[0] = 3;
		idx[1] = 0;
		idx[2] = 2;

		idx[3] = 2;
		idx[4] = 0;
		idx[5] = 1;

		hr = quad->UnlockIndexBuffer();
		SHOW_ERROR_MSG(hr, L"Error unlocking vertex buffer.");
	}

	
	int size = quad->GetAttributeTable(NULL,NULL);
	// Attribute Buffer
	{
		DWORD* attributeBuffer = 0;
		hr = quad->LockAttributeBuffer(0, &attributeBuffer);
		SHOW_ERROR_MSG(hr, L"Error locking attribute buffer.");
		if(!FAILED(hr) )
		{
			attributeBuffer[0] = 0;
		}
		hr = quad->UnlockAttributeBuffer();
		SHOW_ERROR_MSG(hr, L"Error unlocking attribute buffer.");
	}

	return quad;
}

void Util::writeLine(wstring line)
{
	lineQueue.push_back(line);
}